package scene;


// KeyStereoCamera.java
// Andrew Davison, ad@fivedots.coe.psu.ac.th, June 2007

/* This class manages two views of the scene, maintained
   by two instances of the EyeCamera class.

   It also stores the position of the player, which is
   mid-way between the two eye cameras.

   The supported user navigation keys are:
     * translate left, right, forward, back
     * turn left, right
     * reset to starting position  (the 'r' key)
*/

import java.awt.event.*;
import java.text.DecimalFormat;

import javax.media.opengl.*;
import javax.media.opengl.glu.*;



public class KeyStereoCamera
{
  // initial player position
  private static final double X_START = 0.0;
  private static final double Y_START = 0.7;
  private static final double Z_START = 5.0;

  // player movement constants
  private final static double SPEED = 0.4;
  private final static double LOOK_AT_DIST = 100.0;

  // translation and rotation increments
  private static final double MOVE_INCR = 0.1;
  private static final double ANGLE_INCR = 5.0;   // degrees


  // eye cameras
  private boolean isCrossed;
  private EyeCamera leftCamera, rightCamera;

  // player positioning
  private double xPlayer, yPlayer, zPlayer;   // (x,y,z) player position
  private double xLookAt, yLookAt, zLookAt;
  private double xStep, zStep;
  private double viewAngle;

  private DecimalFormat df = new DecimalFormat("0.##");  // 2 dp



  public KeyStereoCamera(GL gl, GLU glu, boolean isCrossed)
  {
    this.isCrossed = isCrossed;
    if (isCrossed)
      System.out.println("Using cross-eyed viewing");
    else
      System.out.println("Using parallel viewing");

    // create the eye cameras
    leftCamera = new EyeCamera(gl, glu, EyeCamera.LEFT_EYE);
    rightCamera = new EyeCamera(gl, glu, EyeCamera.RIGHT_EYE);

    reset();
  } // end of KeyStereoCamera()


  private void reset()
  // set player starting position and orientation
  {
    xPlayer = X_START;
    yPlayer = Y_START;
    zPlayer = Z_START;

    viewAngle = -90.0;   // along -z axis
    xStep = Math.cos( Math.toRadians(viewAngle));  // step distances
    zStep = Math.sin( Math.toRadians(viewAngle));

    xLookAt = xPlayer + (LOOK_AT_DIST * xStep);   // look-at posn
    yLookAt = 0;
    zLookAt = zPlayer + (LOOK_AT_DIST * zStep);
  }  // end of reset()



  public void updateViewVals(int width, int height)
  /* Update the viewport and frustum dimensions based on
     the new window dimensions: width-by-height */
  {
    if (isCrossed) {  // cross-eyed viewing  (right | left position)
//      rightCamera.updateViewVals(0, 0, width/2, height);
//      leftCamera.updateViewVals(width/2, 0, width/2, height);
      rightCamera.updateViewVals(0, 0, width, height);
      leftCamera.updateViewVals(0, 0, width, height);
    }
    else {  // parallel viewing  (left | right position)
//      leftCamera.updateViewVals(0, 0, width/2, height);
//      rightCamera.updateViewVals(width/2, 0, width/2, height);
      rightCamera.updateViewVals(0, 0, width, height);
      leftCamera.updateViewVals(0, 0, width, height);
    }
  }  // end of updateViewVals()


  public void processKey(KeyEvent e)
  /* Process the navigation keys:
     * translate left, right, forward, back
     * turn left, right
     * reset to starting position/orientation  (the 'r' key)
  */
  {
    int keyCode = e.getKeyCode();

    if (keyCode == KeyEvent.VK_R)  // reset
      reset();
    else if (keyCode == KeyEvent.VK_LEFT) {    // left
      if (e.isControlDown()) {   // translate left
        xPlayer += zStep * SPEED;
        zPlayer -= xStep * SPEED;
      }
      else {  // turn left
        viewAngle = (viewAngle - ANGLE_INCR) % 360;
        xStep = Math.cos( Math.toRadians(viewAngle));
        zStep = Math.sin( Math.toRadians(viewAngle));
      }
    }
    else if (keyCode == KeyEvent.VK_RIGHT) {  // right
      if (e.isControlDown()) {   // translate right
        xPlayer -= zStep * SPEED;
        zPlayer += xStep * SPEED;
      }
      else {  // turn right
        viewAngle = (viewAngle + ANGLE_INCR) % 360;
        xStep = Math.cos( Math.toRadians(viewAngle));
        zStep = Math.sin( Math.toRadians(viewAngle));
      }
    }
    else if (keyCode == KeyEvent.VK_UP) {   // move forward
      xPlayer += xStep * SPEED;
      zPlayer += zStep * SPEED;
    }
    else if (keyCode == KeyEvent.VK_DOWN) {  // move back
      xPlayer -= xStep * SPEED;
      zPlayer -= zStep * SPEED;
    }

    // calculate new look-at point
    xLookAt = xPlayer + (xStep * LOOK_AT_DIST);
    zLookAt = zPlayer + (zStep * LOOK_AT_DIST);
  }  // end of processKey()



  public void set(int eyeType)
  /* Set the viewport and perspective projection frustum for
     a camera, and its position. */
  {
    if (eyeType == EyeCamera.LEFT_EYE)   // left eye
      leftCamera.set(xPlayer, yPlayer, zPlayer,
                             xLookAt, yLookAt, zLookAt);
    else  // right eye
      rightCamera.set(xPlayer, yPlayer, zPlayer,
                              xLookAt, yLookAt, zLookAt);
  } // end of set()



  // --------- get player position and orientation --------------

  public String getPos()
  // return the current player position
  {
    return "Pos: (" + df.format(xPlayer) + ", " +
                       df.format(yPlayer) + ", " +
                       df.format(zPlayer) + ")";
  }


  public String getRots()
  // return the current player y-axis rotation
  {  return "yRot: " + (viewAngle+90)%360;  }  // so 0 is along -z axis


}  // end of KeyStereoCamera class